﻿using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;

namespace SocialKit.LightRest
{
    /// <summary>
    /// Provides methods to read xml type of http body of a SocialKit.LightRest.HttpResponseMessage.
    /// </summary>
    public static class XmlResponseExtensions
    {
        /// <summary>
        /// Returns an XmlReader or null if the content is empty from the response message.
        /// </summary>
        /// <param name="response">The response message.</param>
        /// <returns></returns>
        public static XmlReader ReadContentAsXmlReader(this HttpResponseMessage response)
        {
            var settings = new XmlReaderSettings
            {
                CloseInput = true,
                ConformanceLevel = ConformanceLevel.Auto,
                IgnoreWhitespace = true,
                IgnoreProcessingInstructions = true,
#if !PocketPC
                MaxCharactersInDocument = 0,
                ProhibitDtd = true
#endif
            };

            return ReadContentAsXmlReader(response, settings);
        }

        /// <summary>
        /// Returns an XmlReader or null if the content is empty from the response message.
        /// </summary>
        /// <param name="response">The response message.</param>
        /// <param name="settings">The XmlReader settings.</param>
        /// <returns>An XmlReader or null if the content is empty.</returns>
        public static XmlReader ReadContentAsXmlReader(this HttpResponseMessage response, XmlReaderSettings settings)
        {
            var stream = response.ReadContentAsStream();

            if (stream.Length == 0)//empty content
                return null;

            return XmlReader.Create(stream, settings);
        }

        /// <summary>
        /// Returns an XElement or null if the content is empty from the response message.
        /// </summary>
        /// <param name="response">The response message.</param>
        /// <returns></returns>
        public static XElement ReadContentAsXElement(this HttpResponseMessage response)
        {
            using (var reader = response.ReadContentAsXmlReader())
            {
                if (reader == null)
                    return null;

                return XElement.Load(reader);
            }
        }

        /// <summary>
        /// Deserialize the content of the response message with specified type.
        /// </summary>
        /// <typeparam name="T">The target type of the serializer.</typeparam>
        /// <param name="response">The response message.</param>
        /// <returns></returns>
        public static T ReadContentAsXmlSerializable<T>(this HttpResponseMessage response)
        {
            return ReadContentAsXmlSerializable<T>(response, new XmlSerializer(typeof(T)));
        }

        /// <summary>
        /// Deserialize the content of the response message with specified type and serializer.
        /// </summary>
        /// <typeparam name="T">The target type of the serializer.</typeparam>
        /// <param name="response">The response message.</param>
        /// <param name="serializer">The serializer.</param>
        /// <returns></returns>
        public static T ReadContentAsXmlSerializable<T>(this HttpResponseMessage response, XmlSerializer serializer)
        {
            using (var reader = response.ReadContentAsXmlReader())
            {
                if (reader == null)
                    return default(T);

                return (T)serializer.Deserialize(reader);
            }
        }

        /// <summary>
        /// Deserialize the content of the response message with specified serializer.
        /// </summary>
        /// <param name="response">The response message.</param>
        /// <param name="serializer">The serializer.</param>
        /// <returns></returns>
        public static object ReadContentAsXmlSerializable(this HttpResponseMessage response, XmlSerializer serializer)
        {
            using (var reader = response.ReadContentAsXmlReader())
            {
                if (reader == null)
                    return null;

                return serializer.Deserialize(reader);
            }
        }
    }
}